package com.atguigu.juc.cas;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @author yanglin
 * @create 2024-01-24 16:41 星期三
 * description:  实现自旋锁
 */
public class SpinLockDemo {

    /**
     * 实现一个自旋锁，复习CAS思想
     * 自旋锁的好处：循环比较获取没有类似wait的阻塞
     * 
     * 通过CAS操作完成自旋锁，A线程进来，调用myLock方法，自己持有锁5秒，B随后进来发现
     * 当前有线程持有锁，所以只能通过自旋等待，知道A释放锁后，B随后抢到
     */
    
    AtomicReference<Thread> atomicReference = new AtomicReference<>();


    /**
     * 使用CAS思想实现加锁功能
     */
    public void lock(){
        Thread thread = Thread.currentThread();
        System.out.println(Thread.currentThread().getName() + "\t" + "---come in");
        while (!atomicReference.compareAndSet(null,thread)){    //抢到锁后跳出循环
            
        }
    }

    /**
     * 使用CAS思想实现解锁功能
     */
    public void unLock(){
        Thread thread = Thread.currentThread();
        atomicReference.compareAndSet(thread,null);
        System.out.println(Thread.currentThread().getName() + "\t" + "---task over");

    }
    
    public static void main(String[] args) {
        SpinLockDemo spinLockDemo = new SpinLockDemo();
        new Thread(() -> {
            spinLockDemo.lock();
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            spinLockDemo.unLock();
        },"A").start();

        //暂停500毫秒，保证线程A先于线程B启动
        try {
            TimeUnit.MILLISECONDS.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        new Thread(() -> {
            spinLockDemo.lock();
            System.out.println("b线程的业务");
            spinLockDemo.unLock();
        },"B").start();
    }
    
}
